package com.luxk.db.storage.impl;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import com.luxk.db.common.ImpactException;
import com.luxk.db.errorcode.ErrorCodeStorage;
import com.luxk.db.tx.Transaction.Change;

public class ChangeFileCreate implements Change {
	
	private static final int FILE_WRITE_SIZE = 1024 * 1024; // 1M
	
	private File targetFile = null;
	private long size = 0;

	public void setTargetFile(File file) {
		this.targetFile = file;
	}
	
	public void setSize(long size) {
		this.size = size;
	}
	
	public void applyDo() throws ImpactException {
		
		assert(this.targetFile != null);
		
		if (!this.targetFile.exists()) {
			try {
				this.targetFile.createNewFile();
			} catch(IOException e) {
				throw new ImpactException(ErrorCodeStorage.ERROR_CREATE_FILE,
						this.targetFile.getAbsolutePath());
			}
		}

		if(this.size > 0) {
			RandomAccessFile file = null;
			byte b1[] = new byte[FILE_WRITE_SIZE];
			
			try  {
				file = new RandomAccessFile(this.targetFile, "rw");

				if(this.targetFile.length() > this.size)
					file.setLength(this.size);
				
				long writeCnt = this.size / FILE_WRITE_SIZE;
				int reminder = (int)(this.size % FILE_WRITE_SIZE);
				
				file.seek(0);
				
				for(long i = 0; i < writeCnt; i++) {
					file.write(b1);
				}
				
				if(reminder > 0) {
					byte b2[] = new byte[reminder];
					file.write(b2);
				}
			} catch(IOException e) {
				throw new ImpactException(ErrorCodeStorage.ERROR_WRITE_FILE,
						this.targetFile.getAbsolutePath(),
						this.size, b1.length);
			} finally {
				if(file != null) try { file.close(); } catch(Exception e) {}
			}
		}
	}
	
	public void applyUndo() throws ImpactException {
		
		assert(this.targetFile != null);
		
		if(this.targetFile.exists())
			this.targetFile.delete();
	}

}
